class HoloFile
  #
  # pod arrtibutes https://guides.cocoapods.org/syntax/podfile.html#pod
  #
  REQUIRED_ATTRS ||= %i[name version git commit tag path branch].freeze
  attr_accessor(*REQUIRED_ATTRS)
  OPTIONAL_ATTRS ||= %i[configurations modular_headers subspecs inhibit_warnings testspecs].freeze
  attr_accessor(*OPTIONAL_ATTRS)

  # 自己添加的额外属性
  attr_accessor :file_path
  attr_accessor :customized

  def initialize
    yield self if block_given?

    # if !@binary.nil?
    #   @changeable = false
    # else
    #   @binary = true
    #   @changeable = true
    # end
  end

  def self.from_file(path)
    pod = eval(File.read(path))
    pod.file_path = path
    pod
  end

  def pod_by(pod_file, options = {})
    setup_pod_with_customized

    options = pod_requirements
    version = options[:version]
    options.delete :version

    real_pod(pod_file, version, options)
  end

  def to_hash
    h = {}

    # cocoapods pod('xx') 属性
    (REQUIRED_ATTRS + OPTIONAL_ATTRS).each do |att|
      value = send att
      h[att.to_s] = value unless value.nil?
    end

    # 自定义属性
    # h['binary'] = @binary
    # h['changeable'] = @changeable
    # h['use_module_map'] = @use_module_map
    # h['use_swift_lint'] = @use_swift_lint

    h
  end

  def to_json
    to_hash.to_json
  end

  def to_s
    options_h = pod_requirements
    version = options_h[:version]
    options_h.delete :version

    options_a = []
    options_h.each do |k, v|
      options_a << if v.is_a? String
                "#{k}: '#{v}'"
              else
                "#{k}: #{v}"
              end
    end

    other_requirements = unless options_a.empty?
                            ', ' + options_a.join(', ')
                          else
                            ''
                          end

    if version
      "pod '#{name}', #{version}#{other_requirements}"
    else
      "pod '#{name}'#{other_requirements}"
    end
  end

  def md5
    Digest::MD5.hexdigest File.read(file_path)
  end

  def ==(other)
    self.class == other.class && md5 == other.md5
  end

  private

  #
  # 根据传入的对于每一个 pod('xx') 调用的【自定义】配置项,
  # 初始化 最终每一个 pod('xx') 属性值
  #
  def setup_pod_with_customized
    setup_pod_git
    setup_pod_commit
    setup_pod_tag
    setup_pod_branch
    setup_pod_version
    setup_pod_path # 必须放在如上属性赋值的后面, 否则会被覆盖
  end

  def setup_pod_git
    return unless customized
    return unless customized['git']

    @git = customized['git']
  end

  def setup_pod_commit
    return unless customized
    return unless customized['commit']

    @commit = customized['commit']
    @tag = nil
    @branch = nil
    @version = nil
  end

  def setup_pod_tag
    return unless customized
    return unless customized['tag']

    @tag = customized['tag']
    @commit = nil
    @branch = nil
    @version = nil
  end

  def setup_pod_branch
    return unless customized
    return unless customized['branch']

    @branch = customized['branch']
    @commit = nil
    @tag = nil
    @version = nil
  end

  def setup_pod_version
    return unless customized
    return unless customized['version']

    @version = customized['version']
    @git = nil
    @commit = nil
    @tag = nil
    @branch = nil
  end

  def setup_pod_path
    return unless customized
    return unless customized['path']

    @path = customized['path']

    @version = nil
    @git = nil
    @commit = nil
    @tag = nil
    @branch = nil
  end

  #
  # 返回 每一个 pod() 调用需要的 requirements 参数
  #
  def pod_requirements
    h = nil

    # 集成组件时, 【必选】参数, 必须互斥
    if version
      h = { version: version }
    elsif path
      h = { path: path }
    elsif git && commit
      h = { git: git, commit: commit }
    elsif git && tag
      h = { git: git, tag: tag }
    elsif git && branch
      # branch is not supported for binary
      puts("`#{name}` is require by `branch`, which is not preferred")
      h = { git: git, branch: branch }
    else
      puts("VirusFile is not valid, `#{name}` will not be required")
    end

    # 其他的【可选】参数
    pod_requirements_optional(h)
  end

  def pod_requirements_optional(h)
    OPTIONAL_ATTRS.each do |att|
      value = send(att)
      h[att] = value unless value.nil?
    end
    h
  end

  def real_pod(pod_file, version, *requirements)
    # pod() 参数调用形式
    #
    # - 1) pod('AFNetworking')
    # - 2) pod('AFNetworking', '2.5.6')
    # - 3) pod('AFNetworking', '2.5.6', key1:'value1', key2:'value2', ...)
    #
    # pod_file.pod(name, [version, *options])

    if version
      pod_file.pod(name, version, *requirements)
    else
      pod_file.pod(name, *requirements)
    end
  end
end
